/*
 * @Author: 李琪 liqi@lark2game.com
 * @Date: 2024-12-07 10:57:20
 * @LastEditors: 李琪 liqi@lark2game.com
 * @LastEditTime: 2024-12-07 17:07:00
 * @FilePath: /cramped-room/assets/Script/Utils/UtilsIndex.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { _decorator, Color, Component, Layers, Node, Sprite, SpriteFrame, UITransform, Vec2, color } from 'cc'
/* @author: seagull  @change:工具函数
 * @date: 2024/11/23 15:11 */
export const createUINode = (name: string = '') => {
  const node = new Node(name)
  //设置大小、Layer:UI_2D,在项目设置里面它的index为25
  const transform = node.addComponent(UITransform)
  transform.setAnchorPoint(0, 1) //左上角
  node.layer = 1 << Layers.nameToLayer('UI_2D')
  return node
}
export const RandomByRange = (min: number, max: number) => {
  return Math.floor(Math.random() * (max - min) + min) //得到一个在 [min, max - 1] 区间内的随机整数
}
export class Tools {
  static readonly instance: Tools = new Tools()

  static _sharedComp: Component = null

  private cachedVec2: Vec2 = Vec2.ZERO
  /**
   * 将字符串转换为数字
   * @param str
   * @param separator 分隔符
   */
  public stringToNumber(str: string, separator = '*'): number[] {
    const ret: number[] = []
    if (str !== undefined && str !== null) {
      str = str.toString()
      const arr = str.split(separator)
      for (let i = 0; i < arr.length; i++) {
        const ss = arr[i]
        if (ss != '') {
          ret.push(Number(ss))
        }
      }
    }
    return ret
  }
  /**
   * 将字符串转换为坐标
   * @param str 字符串
   * @param separator 分隔符
   */
  public stringToPoint(str: string, separator = '*'): Vec2 {
    if (str === '') {
      return Vec2.ZERO
    }

    const arr = str.split(separator).map(Number)
    return new Vec2(arr[0] || 0, arr[1] || 0)
  }

  /*********** json 数据设置 ***********/

  /**
   * @description: 设置表里的boolean值
   * @param {any} jsData jsData
   * @param {string} ownProperty 属性
   * @param defaultValue 默认返回值
   * @return {*} 返回boolean值
   */
  public setBoolean(jsData: any, ownProperty: string, defaultValue = false): boolean {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const bool = Boolean(value)
      if (bool != bool) {
        // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不为Bool", jsData[ownProperty]);
        return defaultValue
      }
      return bool
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return defaultValue
  }

  /**
   * @description: 设置表里的整型数字
   * @param {any} jsData jsData
   * @param {string} ownProperty 属性
   * @return {*} 为nan或者不存在这个参数的时候 返回0,否则返回整型数字
   */
  public setInt(jsData: any, ownProperty: string, defaultRet = 0): number {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      if (value !== '') {
        const param = parseInt(value)
        if (param != param) {
          // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不为数字", jsData[ownProperty]);
          return defaultRet
        }
        return param
      }

      return defaultRet
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return defaultRet
  }

  public setIntArr(jsData: any, ownProperty: string, separator = '*'): number[] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      let ret = null
      if (separator) {
        ret = []
        const str = String(value)
        const arr = str.split(separator)
        for (let i = 0; i < arr.length; i++) {
          let ss = arr[i]
          ss = ss.trim()
          if (ss != '') {
            ret.push(parseInt(ss))
          }
        }
      } else if (Array.isArray(value)) {
        ret = value
      } else {
        ret = []
      }
      return ret
    }
    return []
  }

  /**
   * @description: 设置表里的dict
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setIntDict(jsData: any, ownProperty: string | number, defaultRet: any = {}): { [key: number]: number } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const id: number = parseInt(key)
          const lv: number = parseInt(value[id])
          dict[id] = lv
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * @description: 设置表里的dict
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setStringDict(jsData: any, ownProperty: string | number, defaultRet: any = {}): { [key: number]: string } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const id: number = parseInt(key)
          const lv: string = value[id]
          dict[id] = lv
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * 设置表里的dict
   * @param jsData
   * @param ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setIntDictDict(
    jsData: any,
    ownProperty: string | number,
    defaultRet: any = {},
  ): { [key: number]: { [key: number]: number } } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict: { [key: number]: { [key: number]: number } } = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const id: number = parseInt(key)
          const subDict: { [key: number]: number } = this.setIntDict(value, id.toString())
          dict[id] = subDict
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * @description: 设置表里的dict
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setIntArrDict(jsData: any, ownProperty: string | number, defaultRet: any = {}): { [key: number]: number[] } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict: { [key: number]: number[] } = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const id: number = parseInt(key)
          const lv: number[] = value[id]
          dict[id] = lv
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * @description: 设置表里的dict
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setStrArrDict(jsData: any, ownProperty: string | number, defaultRet: any = {}): { [key: number]: string[] } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict: { [key: number]: string[] } = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const content: string[] = value[key]
          dict[key] = content
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * 设置表里的dict
   * @param jsData
   * @param ownProperty 属性
   * @param defaultRet 默认返回值
   */
  public setIntArrDictDict(
    jsData: any,
    ownProperty: string | number,
    defaultRet: any = {},
  ): { [key: number]: { [key: number]: number[] } } {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict: { [key: number]: { [key: number]: number[] } } = {}
      const value = jsData[ownProperty]
      if (value != '') {
        for (const key in value) {
          const id: number = parseInt(key)
          const subDict: { [key: number]: number[] } = this.setIntArrDict(value, id.toString())
          dict[id] = subDict
        }
        return dict
      }
      return defaultRet
    }
    return defaultRet
  }

  /**
   * @description: 设置表里的数字
   * @param {any} jsData jsData
   * @param {string} ownProperty 属性
   * @return {*} 为nan或者不存在这个参数的时候 返回0,否则返回数字
   */
  public setNum(jsData: any, ownProperty: string, defaultValue = 0): number {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const num = Number(value)
      if (num != num) {
        // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不为数字", jsData[ownProperty]);
        return defaultValue
      }
      return num
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return defaultValue
  }

  /**
   * @description: 设置表里的数组
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param {*} separator 切分符号,默认是 "*"
   * @param {number} hopeLength 希望这个数组的长度,如果导出的长度不等于这个长度会warn提示
   * @return {*} 分隔符，存储数据使用改的话，这里要是null
   */
  public setNumArr(jsData: any, ownProperty: string, hopeLength?: number, separator = '*'): number[] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const str = value
      let arr = null
      if (separator) {
        arr = GMTools.stringToNumber(str, separator)
      } else {
        arr = str
      }
      if (arr.length == 0) {
        // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "的数组长度为0");
      }
      if (hopeLength && arr.length != hopeLength) {
        // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "的数组长度不为", hopeLength);
      }
      return arr
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return []
  }

  /** number[][] */
  public setNumArrD(jsData: any, ownProperty: string, sp1 = '#', sp2 = '*'): number[][] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const str = value
      let arr = null
      if (sp1) {
        arr = []
        const tmpArr = this.setStringArr(jsData, ownProperty, sp1)
        for (let i = 0; i < tmpArr.length; i++) {
          const tmp = tmpArr[i]
          if (tmp && tmp != '') {
            const a = GMTools.stringToNumber(tmp, sp2)
            arr.push(a)
          }
        }
      } else {
        arr = str
      }
      return arr
    }
    return []
  }

  /**
   * @description: 设置表里的dict
   * @param {any} jsData
   * @param {string} ownProperty 属性
   */
  public setNumDict(jsData: any, ownProperty: string): {} {
    if (jsData.hasOwnProperty(ownProperty)) {
      const dict = {}
      const value = jsData[ownProperty]
      for (const key in value) {
        const id = Number(key)
        const lv = Number(value[id])
        dict[id] = lv
      }
      return dict
    }
    return {}
  }

  /**
   * 设置vec坐标数据
   * @param jsData
   * @param ownProperty
   * @param hopeLength
   * @param separator
   * @returns
   */
  public setVec2(jsData: any, ownProperty: string, separator = '*'): Vec2 {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const str = value
      const pos = GMTools.stringToPoint(str, separator)
      return pos
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return Vec2.ZERO
  }

  public setVec2Arr(jsData: any, ownProperty: string): Vec2[] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value: string = jsData[ownProperty]
      const tmpArr = []
      if (value != '') {
        const arr = value.split('#')
        for (let i = 0; i < arr.length; i++) {
          const pos = GMTools.stringToPoint(arr[i], '*')
          tmpArr.push(pos)
        }
      }
      return tmpArr
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return []
  }

  /** item数量 */
  public setItemArr(jsData: any, ownProperty: string): { id: number; count: number }[] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value: string = jsData[ownProperty]
      const tmpArr = []
      if (value != '') {
        const arr = value.split('#')
        for (let i = 0; i < arr.length; i++) {
          const tmp = GMTools.stringToNumber(arr[i]) // arr[i].split('*');
          if (tmp.length > 1) {
            tmpArr.push({ id: tmp[0], count: tmp[1] })
          }
        }
      }
      return tmpArr
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return []
  }

  /**
   * @description: 设置表里的数组
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @return {*} 返回字符串
   */
  public setString(jsData: any, ownProperty: string): string {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      return String(value)
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return ''
  }

  /**
   * @description: 设置表里字符串数组
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @param {string} separator 切分符 默认为 "*"
   * @param {number} hopeLength 希望这个数组的长度,如果导出的长度不等于这个长度会warn提示
   * @return {*}除了没有这个属性返回[],否则返回表里配置的数组
   */
  public setStringArr(jsData: any, ownProperty: string, separator = '*', hopeLength?: number): string[] {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const str = String(value)
      if (str == '') {
        return []
      }
      if (separator) {
        const arr = str.split(separator)
        if (arr.length == 0) {
          // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "的数组长度为0");
        }
        if (hopeLength && arr.length != hopeLength) {
          // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "的数组长度不为", hopeLength);
        }
        return arr
      }
      if (Array.isArray(value)) {
        return value
      }
      return []
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return []
  }

  /**
   * @description: 设置表里的颜色
   * @param {any} jsData
   * @param {string} ownProperty 属性
   * @return {*} 返回字符串
   */
  public setColor(jsData: any, ownProperty: string, separator = '*'): Color {
    let decolor = color(255, 255, 255)
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const str = String(value)
      if (str != '') {
        const arr = str.split(separator)
        if (arr.length == 3) {
          decolor = color(Number(arr[0]), Number(arr[1]), Number(arr[2]))
        }
      }
    }

    return decolor
  }

  /** 设置自定义数据 */
  public setJsonData<T>(jsData: any, ownProperty: string, data: new () => T): T {
    if (jsData.hasOwnProperty(ownProperty)) {
      const value = jsData[ownProperty]
      const ret = new data()
      ret['loadJson'](value)
      return ret
    }
    // console.warn(this.tableName, "表中 id为", this.id, "的", ownProperty, "不存在");
    return null
  }

  public setJsonDataArr<T>(jsData: any, ownProperty: string, temp: new () => T) {
    const arr = []
    if (jsData.hasOwnProperty(ownProperty)) {
      const values = jsData[ownProperty]
      if (values && values.length > 0) {
        for (let i = 0; i < values.length; i++) {
          const data = new temp()
          data['loadJson'](values[i])
          arr.push(data)
        }
      }
    }

    return arr
  }

  /** 字典格式 */
  public setJsonDataDict<T>(jsData: any, ownProperty: string, temp: new () => T) {
    const dict: { [key: number]: T } = {}
    if (jsData.hasOwnProperty(ownProperty)) {
      const param = jsData[ownProperty]
      for (const key in param) {
        const id: number = parseInt(key)
        const tmp = param[key]
        if (tmp) {
          const data = new temp()
          data['loadJson'](tmp)
          dict[id] = data
        } else {
          GMTools.error('error json data dict ', ownProperty)
        }
      }
    }

    return dict
  }

  public setJsonDataArrDict<T>(jsData: any, ownProperty: string, temp: new () => T): { [key: number]: T[] } {
    const dict: { [key: number]: T[] } = {}
    if (jsData.hasOwnProperty(ownProperty)) {
      const param = jsData[ownProperty]
      for (const key in param) {
        const id: number = parseInt(key)
        const arr: T[] = []
        const values = param[key]
        if (values) {
          for (let i = 0; i < values.length; i++) {
            const data = new temp()
            data['loadJson'](values[i])
            arr.push(data)
          }
        }
        dict[id] = arr
      }
    } else {
      GMTools.warn('error json data array dict ', ownProperty)
    }

    return dict
  }

  /** 二维字典 */
  public setJsonDataDictDict<T>(
    jsData: any,
    ownProperty: string,
    temp: new () => T,
  ): { [key: number]: { [key: number]: T } } {
    const dict: { [key: number]: { [key: number]: T } } = {}
    if (jsData.hasOwnProperty(ownProperty)) {
      const param = jsData[ownProperty]
      for (const key in param) {
        const id: number = parseInt(key)
        const values = param[key]
        if (values) {
          dict[id] = this.setJsonDataDict(values, ownProperty, temp)
        }
      }
    } else {
      GMTools.error('error json data dict dict ', ownProperty)
    }

    return dict
  }

  /**
   * 获取一个从0到n的整数数组
   */
  public getIntArr(end: number, start = 0) {
    const arr: number[] = []
    for (let i = start; i <= end; i++) {
      arr.push(i)
    }
    return arr
  }
  /**
   * log输出
   * @param txt
   */
  public log(message?: any, ...optionalParams: any[]) {}

  /**
   * error输出
   * @param txt
   */
  public error(message?: any, ...optionalParams: any[]) {
    console.error(message, ...optionalParams)
  }

  /**
   * warn输出
   * @param txt
   */
  public warn(message?: any, ...optionalParams: any[]) {
    console.warn(message, ...optionalParams)
  }
}
export const GMTools = Tools.instance
